package com.xiang.aspect;

import com.alibaba.fastjson.JSONObject;
import com.xiang.annotation.AccessLimit;
import com.xiang.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
@Slf4j
public class AccessLimitAspect {
  private final RedisTemplate<String, Object> redisTemplate;

  @Autowired
  public AccessLimitAspect(RedisTemplate<String, Object> redisTemplate) {
    this.redisTemplate = redisTemplate;
  }

  @Around("execution(* *(..)) && @annotation(accessLimit)")
  public Object accessLimit(ProceedingJoinPoint joinPoint, AccessLimit accessLimit) throws Throwable {
    long start = System.currentTimeMillis();
    // 获取方法名和参数列表
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Method method = signature.getMethod();
    String methodName = method.getName();
    Object[] args = joinPoint.getArgs();

    // 获取请求路径和IP地址
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    // before: IP限流
//    String requestPath = request.getRequestURI();
//    String ipAddress = oConvertUtils.getIpAddrByRequest(request);
    // 计算Redis键名
//    String key = String.format("%s:%s:%s", methodName, requestPath, ipAddress);

    // update: 手机号限流
    JSONObject requestBody = getRequestBody(request);
    String mobile = requestBody.getString("mobile");
    if(Objects.isNull(mobile)|| StringUtils.isBlank(mobile)){
      log.error("手机号为空！");
      return joinPoint.proceed(args);
    }
    log.info("手机号：{}",mobile);
    String key = String.format("%s:%s", methodName, mobile);
    // 从Redis中获取访问次数
    Integer count = (Integer) redisTemplate.opsForValue().get(key);
    if (count == null) {
      count = 0;
    }

    // 判断访问次数是否超限
    if (count >= accessLimit.limit()) {
      return Result.error("访问次数超限");
    }
    // 计算限制时间段
    long limitSeconds = accessLimit.seconds();
    // 记录访问次数，并将访问次数存储到Redis中
    redisTemplate.opsForValue().set(key, count + 1, limitSeconds, TimeUnit.SECONDS);

    long end = System.currentTimeMillis();
    log.info("耗时：{} 毫秒",(end-start));
    // 执行方法
    return joinPoint.proceed(args);
  }

  private JSONObject getRequestBody(HttpServletRequest request) throws IOException {
    //自定义从bodyt中获取json格式数据
    StringBuffer sb = new StringBuffer();
    String line = null;
    try {
      BufferedReader reader = request.getReader();
      while ((line = reader.readLine()) != null){
//        System.out.println("line :"+line);
        sb.append(line);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    // 将请求体中的JSON字符串转换为JSONObject对象
    return JSONObject.parseObject(sb.toString());
  }

}
